// #define VERSION     2007051800
#define MODULE      ypipi_h5
#define MODULENAME "ypipi_h5"
#define MODULEDCL   mdcl_ypipi_h5

// #define ROOTFILENAME MODULENAME/* */".root"

#include <fstream>
#include <iostream>
#include <map>
#include <string>

// #include <stdio.h>
#include <belle.h>
#include <event/BelleEvent.h>
#include <basf/module.h>
#include <basf/module_descr.h>
//#include <particle/Particle.h>
//#include <particle/ParticleUserInfo.h>
#include MDST_H
#include <kid/atc_pid.h>

//#include <cabs3/Plist.h>
 
#include <pytpp.hpp>
#include <rows/ypipi_pi0row.hpp>
#include <rows/ypipi_ctrkrow.hpp>
#include <rows/ypipi_trk_indexrow.hpp>

using namespace std;

#if defined(BELLE_NAMESPACE)
namespace Belle {
#endif

enum hyp_t {
  UNDEF=-1, ELEC=0, MUON=1, PION=2, KAON=3, PROT=4, GAMM=5,
  PI0=6, ETA=7, K0S=8, LAM=9, ALM=10, CONV=11, NHYP=12 };

class MODULE : public Module {
public:
  MODULE();
  ~MODULE() {}
  
  void init(int *) {}
  void disp_stat(const char *) {}
  void begin_run(BelleEvent *, int *) {} // no begin_run in this module
  void end_run(BelleEvent *, int *) {}
  
  void hist_def() {};
  void event(BelleEvent *, int *);
  void term();
  
private:
  unsigned long _eventcount;
  //  map<string, int> _ypipi_h5_ev;
  ofstream _ofs;
  atc_pid _pid;
  pyt::table<ypipi_pi0row_t>* nt_pi0;
  ypipi_pi0row_t* pi0row; 
  pyt::table<ypipi_ctrkrow_t>* nt_ctrk;
  ypipi_ctrkrow_t* ctrkrow; 
  pyt::table<ypipi_trk_indexrow_t>* nt_index;
  ypipi_trk_indexrow_t* indexrow; 

  int ctrk_index;
  int pi0_index;
//   enum { PI=0, K=1, NCHGTYP=2 };
//   Particles all_plus[NCHGTYP], all_minus[NCHGTYP];
//   Particles all_d0_kpi;  // D0 -> K- pi+ (D0bar -> K+ pi- list is hidden)
//   mystat *m_stat;
//   TH1F *h_mkpi1;
//   TH1F *h_mkpi2;
//   TH1F *h_mkpi3;
//   TH1F *h_mkpi4;
//  TObjArray hlist;
};

  extern "C" Module_descr *
  MODULEDCL()
  {
    Module_descr *dscr = new Module_descr(MODULENAME, new MODULE);
    return dscr;
  }

  MODULE::MODULE():
    _eventcount(0),
    ctrk_index(0),
    pi0_index(0)
  {
    this->_ofs.open("ypipi.txt");
    this->nt_pi0 = pyt::open_table<ypipi_pi0row_t>("ypipi_pi0.h5", "nt", "w");
    this->pi0row = new ypipi_pi0row_t;
    this->nt_ctrk = pyt::open_table<ypipi_ctrkrow_t>("ypipi_ctrk.h5", "nt", "w");
    this->ctrkrow = new ypipi_ctrkrow_t;
    this->nt_index = pyt::open_table<ypipi_trk_indexrow_t>("ypipi_index.h5", "nt", "w");
    this->indexrow = new ypipi_trk_indexrow_t;

    // banner
    //   printf("%s: ---------------------\n", MODULENAME);
    //   printf("%s: version %d\n",            MODULENAME, VERSION);
    //   printf("%s: ---------------------\n", MODULENAME);
    
    //   // for statistics
    //   m_stat = new mystat(MODULENAME);  // for event statistics
    //   m_stat->countname(1, "n(K-pi+)"); // counter for D0 -> K- pi+ candidates
    //   m_stat->countname(2, "n(K+pi-)"); // counter for D0 -> K+ pi- candidates
    
    //   // cabs3 initializations
    //   nk::PlistBase::set_ptype_charge_conjugate("D0","D0B");
    //   char *name_plus[]  = {"PI+", "K+"};
    //   char *name_minus[] = {"PI-", "K-"};
    //   for (int i=0; i<NCHGTYP; i++) {
    //     all_plus[i].set(name_plus[i]);
    //     all_minus[i].set(name_minus[i], all_plus[i]); // define charge conjugation
    //   }
    //   all_d0_kpi.set("D0", nk::AutoConj);
    
    //   // other initialization
    //   pinfo::init_pid();
    
    // ROOT histogram initializations
    //   hlist.Add(h_mkpi1 = new TH1F("mkpi1", "m(K-pi+)1", 100, 1.8, 1.9));
    //   hlist.Add(h_mkpi2 = new TH1F("mkpi2", "m(K-pi+)2", 100, 1.8, 1.9));
    //   hlist.Add(h_mkpi3 = new TH1F("mkpi3", "m(K-pi+)3", 100, 1.8, 1.9));
    //   hlist.Add(h_mkpi4 = new TH1F("mkpi4", "m(K-pi+)4", 100, 1.8, 1.9));
  }


// ----------------------------------------------------------------------
// MODULE::term
// ----------------------------------------------------------------------
void
MODULE::term()
{
  cout << "CRAIG: In MODULE::term(), track summary:" << endl;
  delete this->nt_ctrk;
  delete this->nt_pi0;
  delete this->nt_index;
  delete this->ctrkrow;
  delete this->pi0row;
  delete this->indexrow;

  // summarize event statistics
//   m_stat->term();

//   // save histograms
//   const char *filename    = MODULENAME/* */".root";
//   const char *description = MODULENAME;

 
  
//   hlist.Write();
//   hfile->Close();
}

// ----------------------------------------------------------------------
// MODULE::event
// ----------------------------------------------------------------------
void
MODULE::event(BelleEvent *, int *)
{

  
  Mdst_charged_Manager& m_charged       = Mdst_charged_Manager::get_manager();
  Mdst_muid_Manager& m_muid             = Mdst_muid_Manager::get_manager();  

  if (m_charged.count() != m_muid.count()) {
    cout << "CRAIG: In MODULE::event(): Event " << this->_eventcount 
	 << " has mismatch between nctrk and nmuid (" << m_charged.count() << " != " 
	 << m_muid.count() << ")" << endl;
    this->_eventcount++;
    return;
  }

  int nctrk = m_charged.count();

  this->indexrow->eventno    = this->_eventcount;
  this->indexrow->nctrk      = m_charged.count();
  this->indexrow->ctrk_start = this->ctrk_index;

  for (int i=0; i < nctrk; i++) {
    this->ctrkrow->eventno  = this->_eventcount;
    this->ctrkrow->trackno  = this->ctrk_index;
    
    this->ctrkrow->charge   = m_charged[i].charge();
    this->ctrkrow->px       = m_charged[i].px();
    this->ctrkrow->py       = m_charged[i].py();
    this->ctrkrow->pz       = m_charged[i].pz();
    this->ctrkrow->mass     = m_charged[i].mass();
    this->ctrkrow->used_pid = m_charged[i].used_pid();
    this->ctrkrow->pid_e    = m_charged[i].pid_e();
    this->ctrkrow->pid_mu   = m_charged[i].pid_mu();
    this->ctrkrow->pid_pi   = m_charged[i].pid_pi();
    this->ctrkrow->pid_K    = m_charged[i].pid_K();
    this->ctrkrow->pid_p    = m_charged[i].pid_p();
    
    this->ctrkrow->quality  = m_muid[i].quality();
    this->ctrkrow->muon     = m_muid[i].muon();
    
    this->nt_ctrk->append(*(this->ctrkrow));      
   
    this->ctrk_index++;
  }

  Mdst_pi0_Manager& m_pi0 = Mdst_pi0_Manager::get_manager();

  this->indexrow->npi0      = m_pi0.count();
  this->indexrow->pi0_start = this->pi0_index;
  
  for (int i=0; i < m_pi0.count(); i++) {
    this->pi0row->eventno  = this->_eventcount;
    this->pi0row->trackno  = this->pi0_index;
    
    this->pi0row->px       = m_pi0[i].px();
    this->pi0row->py       = m_pi0[i].py();
    this->pi0row->pz       = m_pi0[i].pz();
    this->pi0row->mass     = m_pi0[i].mass();
    this->pi0row->energy   = m_pi0[i].energy();
    this->pi0row->chisq    = m_pi0[i].chisq();

    this->nt_pi0->append(*(this->pi0row));      
   
    this->pi0_index++;
  }

  this->_eventcount++;
  
  //  cout << "CRAIG : MADE IT TO APPEND with " << this->nt_index->nrows() << " WRITTEN!" << endl;
  this->nt_index->append(*(this->indexrow));

  
}


#if defined(BELLE_NAMESPACE)
}
#endif
